home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file is part of ixemul.library for the Amiga.
- * Copyright (C) 1991, 1992 Markus M. Wild
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * _main.c,v 1.1.1.1 1994/04/04 04:30:43 amiga Exp
- *
- * _main.c,v
- * Revision 1.1.1.1 1994/04/04 04:30:43 amiga
- * Initial CVS check in.
- *
- * Revision 1.3 1992/08/09 20:41:54 amiga
- * change to use 2.x header files by default
- * add option to ignore global environment (ix.ix_ignore_global_env).
- *
- * Revision 1.2 1992/07/04 19:10:06 mwild
- * add call to ix_install_sigwinch().
- *
- * Revision 1.1 1992/05/17 21:01:29 mwild
- * Initial revision
- *
- *
- */
-
- #define _KERNEL
- #include "ixemul.h"
- #include "kprintf.h"
-
- #include <dos/var.h>
- #include <workbench/startup.h>
- #include <dirent.h>
- #include <stdio.h>
- #include <string.h>
-
- char **get_global_environment(void)
- {
- DIR *dp;
- struct dirent *de;
- int num_env;
- char **cp, **env;
-
- /* now go for global variables */
-
- dp = (DIR *)syscall (SYS_opendir, "ENV:");
- if (dp == NULL)
- /* `panic!', no ENV: logical ! */
- return NULL;
-
- /* first count how many entries we have */
- for (num_env = 0; syscall(SYS_readdir, dp); num_env++) ;
-
- /* skip . and .. */
- syscall (SYS_rewinddir, dp);
- if ((de = (struct dirent *) syscall (SYS_readdir, dp))
- && de->d_namlen == 1 && de->d_name[0] == '.' && --num_env &&
- (de = (struct dirent *) syscall (SYS_readdir, dp))
- && de->d_namlen == 2 && de->d_name[0] == '.' && de->d_name[1] == '.')
- {
- num_env --;
- de = (struct dirent *) syscall (SYS_readdir, dp);
- }
-
- if ((cp = (char **)kmalloc((num_env + 1) * 4)))
- env = cp;
- else
- /* out of memory !!! */
- return NULL;
-
- for (; de; de = (struct dirent *) syscall (SYS_readdir, dp))
- {
- struct stat stb;
- int len = 0;
- char envfile[MAXPATHLEN];
-
- /* Don't include variables with funny names, and don't include
- multiline variables either, they totally confuse ksh.. */
- if (strchr(de->d_name, '.'))
- continue;
-
- sprintf (envfile, "ENV:%s", de->d_name);
-
- if (syscall(SYS_stat, envfile, &stb) == 0)
- {
- len = stb.st_size;
- /* skip directories... shudder */
- if (!S_ISREG (stb.st_mode))
- continue;
- }
-
- /* NAME=CONTENTS\0 */
- *cp = (char *)kmalloc(de->d_namlen + 1 + len + 1);
- if (*cp)
- {
- int written = sprintf (*cp, "%s=", de->d_name);
- int fd;
-
- if (len)
- {
- fd = syscall(SYS_open, envfile, 0);
- if (fd >= 0)
- {
- written += syscall(SYS_read, fd, *cp + written, len);
- (*cp)[written] = 0;
- if ((*cp)[--written] == '\n')
- (*cp)[written] = 0;
- syscall(SYS_close, fd);
- }
-
- /* now filter out those multiliners (that is,
- variables containing \n, you can have variables
- as long as want, but don't use \n... */
- if (strchr(*cp, '\n'))
- {
- kfree(*cp);
- continue;
- }
- }
- }
- else
- break;
-
- cp++;
- }
-
- *cp = 0;
- syscall (SYS_closedir, dp);
- return env;
- }
-
- static char **__get_environ (void)
- {
- static char *endmarker = 0;
- char **env = &endmarker;
- int num_env, num_local = 0;
- char **cp, **tmp;
- struct Message *msg;
- struct MsgPort *port;
-
- /* 2.0 local environment overrides 1.3 global environment */
- struct Process *me = (struct Process *)FindTask (0);
- struct LocalVar *lv, *nlv;
-
- /* count total number of local variables (skip aliases) */
- for (num_local = 0, lv = (struct LocalVar *)me->pr_LocalVars.mlh_Head;
- (nlv = (struct LocalVar *)lv->lv_Node.ln_Succ);
- lv = nlv)
- if (lv->lv_Node.ln_Type == LV_VAR)
- num_local++;
-
- if ((cp = (char **) syscall (SYS_malloc, (num_local + 1) * 4)))
- {
- env = cp;
-
- for (lv = (struct LocalVar *)me->pr_LocalVars.mlh_Head;
- (nlv = (struct LocalVar *)lv->lv_Node.ln_Succ);
- lv = nlv)
- {
- /* I'm not interested in aliases, really not ;-)) */
- if (lv->lv_Node.ln_Type != LV_VAR)
- continue;
-
- /* NAME=CONTENTS\0 */
- *cp = (char *)syscall(SYS_malloc, strlen(lv->lv_Node.ln_Name)
- + 1 + lv->lv_Len + 1);
- if (*cp)
- sprintf (*cp, "%s=%*.*s", lv->lv_Node.ln_Name,
- (int)lv->lv_Len, (int)lv->lv_Len, lv->lv_Value);
- else
- break;
- cp++;
- }
- *cp = NULL;
- }
- else
- return env;
-
- if (ix.ix_flags & ix_ignore_global_env)
- return env;
-
- port = ix.ix_notify_request.nr_stuff.nr_Msg.nr_Port;
- if (port == NULL)
- {
- if ((port = CreatePort(NULL, 0)))
- {
- ix.ix_notify_request.nr_stuff.nr_Msg.nr_Port = port;
- port->mp_Flags = PA_IGNORE;
- ix.ix_notify_request.nr_Name = "ENV:";
- ix.ix_notify_request.nr_Flags = NRF_SEND_MESSAGE;
- if (!StartNotify(&ix.ix_notify_request))
- {
- DeletePort(port);
- ix.ix_notify_request.nr_stuff.nr_Msg.nr_Port = NULL;
- return env;
- }
- }
- else
- return env;
- }
- if (ix.ix_global_environment == NULL)
- ix.ix_global_environment = get_global_environment();
- else if ((msg = GetMsg(port)))
- {
- do
- {
- ReplyMsg(msg);
- } while ((msg = GetMsg(port)));
-
- /* free the old environment */
- for (tmp = ix.ix_global_environment; *tmp; kfree(*tmp++)) ;
- kfree(ix.ix_global_environment);
-
- ix.ix_global_environment = get_global_environment();
- }
-
- if (ix.ix_global_environment == NULL)
- return env;
-
- for (num_env = 0, tmp = ix.ix_global_environment; *tmp; tmp++, num_env++);
-
- tmp = (char **)syscall (SYS_realloc, env, (num_local + num_env + 1) * 4);
- if (tmp == NULL)
- return env;
- env = tmp;
- cp = &env[num_local];
-
- for (tmp = ix.ix_global_environment; *tmp; tmp++)
- {
- char *p = strchr(*tmp, '='), *f;
- int offset;
-
- *p = 0;
- f = _findenv(env, *tmp, &offset);
- *p = '=';
- if (f)
- continue;
- *cp++ = (char *)syscall(SYS_strdup, *tmp);
- *cp = NULL;
- }
- return env;
- }
-
- /* smells abit kludgy I know.. but can live with quite few variables in
- * the user area
- */
-
- int
- _main (union { char *_aline; struct WBStartup *_wb_msg; } a1,
- union { int _alen; char *_def_window; } a2,
- int (*main)(int, char **, char **))
- #define aline a1._aline
- #define alen a2._alen
- #define wb_msg a1._wb_msg
- #define def_window a2._def_window
- {
- struct Process *me = (struct Process *)SysBase->ThisTask;
- char **argv, **env;
- int argc;
- int exitcode;
-
- KPRINTF (("entered __main()\n"));
- if (! me->pr_CLI)
- {
- /* Workbench programs expect to have their CD where the executed
- * program lives. */
- if (wb_msg->sm_ArgList)
- {
- CurrentDir (wb_msg->sm_ArgList->wa_Lock);
- syscall (SYS__wb_parse, me, wb_msg, def_window);
- }
- /* argc==0: this means, that argv is really a WBenchMsg, not a vector */
- argc = 0;
- argv = (char **) wb_msg;
- }
- else
- {
- /* if we were started from the CLI, alen & aline are valid and
- * should now be split into arguments. This is done by the
- * function "_cli_parse()", which does wildcard expansion if not
- * disabled (see cli_parse.c). */
- _cli_parse (me, alen, aline, &argc, &argv);
- if (is_ixconfig(argv[0]))
- return 10;
- }
-
- env = __get_environ ();
-
- /* this is not really the right thing to do, the user should call
- ix_get_vars2 () to initialize environ to the address of the variable
- in the calling program. However, this setting guarantees that
- the user area entry is valid for getenv() calls. */
- u.u_environ = &env;
-
- ix_install_sigwinch ();
-
- /* The finishing touch :-) Not really necessary, though. */
- errno = 0;
-
- exitcode = main (argc, argv, env);
-
- syscall(SYS_exit,exitcode);
- return 0;
- }
-